/*
 * HashTable.cpp
 *
 *  Created on: Oct 7, 2011
 *      Author: kimi
 */
#include "BasicHashTable.h"

unsigned long BasicHashTable::getTableSize() {
	return tableSize;
}

bool BasicHashTable::increaseHashTableByFactor2() {
	bool res = false;
	for (unsigned int i = 0; i < tableSize; i++) {
		char* entry = NULL;
		res = flrFile->getRecordByID(i,&entry);
		if (res == false)
			return false;

		unsigned long newId = 0;
		res = flrFile->addRecord(&newId,entry);
		if (res == false)
			return false;

		if (newId != i+tableSize)
			return false;
	}

	tableSize*=2;

	// se debe aumentar en 1 la cantidad de bits usados en el hash

	return true;
}


bool BasicHashTable::reduceHashTableByFactor2(){
	tableSize /=2;
	bool res = flrFile->truncateFile(tableSize);
	return res;
}

bool BasicHashTable::getEntry(unsigned long hash, unsigned long* recordNumber, unsigned long* hashSize) {

	/* El archivo esta implementado con FLRFile... por lo que la cant. de registros / tamaño de la tabla
	 * esta implicito en el BasicHashTable. Luego los registros estan ordenados de la siguiente forma:
	 * 	[numero de bloque][tamaño dispersion] ; [numero de bloque][tamaño dispersion] ; ....
	 */
	char* entry = NULL;
	bool res = flrFile->getRecordByID(hash,&entry);

	if (res == false)
		return false;


	unsigned long temp = -1;

	char* ptr = reinterpret_cast<char*>(&temp);
	for (unsigned int i = 0; i < sizeof(unsigned long); i++) {
		*ptr = *(entry + i);
		ptr++;
	}
	(*recordNumber) = temp;

	char* ptr2 = reinterpret_cast<char*>(&temp);
	for (unsigned int i = 0; i < sizeof(unsigned long); i++) {
		*ptr2 = *(entry + i + sizeof(unsigned long));
		ptr2++;
	}
	(*hashSize) = temp;

	//cout << "RN " << (*recordNumber) << " - HS " << (*hashSize) << endl;

	return true;
}

/**
 * crea una entrada al final de la tabla
 */
bool BasicHashTable::addEntry(unsigned long* hash, unsigned long recordNumber, unsigned long hashSize) {

	char*entry = new char[2*sizeof(unsigned long)];

	char* p = reinterpret_cast<char*>(&recordNumber);
	for (unsigned int i = 0; i < sizeof(unsigned long); i++) {
		entry[i] = p[i];
	}

	p = reinterpret_cast<char*>(&hashSize);
	for (unsigned int i = 0; i < sizeof(unsigned long); i++) {
		entry[i+sizeof(unsigned long)] = p[i];
	}

	bool res = flrFile->addRecord(hash,entry);

	return res;
}

/**
 * edita una entrada de la table
 */
bool BasicHashTable::editEntry(unsigned long hash, unsigned long recordNumber, unsigned long hashSize) {

	char* entry = NULL;
	bool res = flrFile->getRecordByID(hash,&entry);

	if (res == false)
		return false;

	char* p = reinterpret_cast<char*>(&recordNumber);
	for (unsigned int i = 0; i < sizeof(unsigned long); i++) {
		entry[i] = p[i];
	}

	p = reinterpret_cast<char*>(&hashSize);
	for (unsigned int i = 0; i < sizeof(unsigned long); i++) {
		entry[i+sizeof(unsigned long)] = p[i];
	}

	res = flrFile->updateRecord(hash,entry);

	return res;
}

void BasicHashTable::purge() {
	flrFile->purge();
	tableSize = flrFile->getRecordCount();
}

void BasicHashTable::setTableSize(unsigned long size) {
	tableSize = size;
}

BasicHashTable::BasicHashTable(string xFilePath) {
	filePath = xFilePath;
	flrFile = new FLRFile(xFilePath,2*sizeof(unsigned long));
	tableSize = flrFile->getRecordCount();
}


BasicHashTable::~BasicHashTable() {

}
